package com.sd.repay.task;


import com.sd.repay.pojo.PayOrder;
import com.sd.repay.service.AroundPayOrderService;
import com.sd.repay.service.PayOrderService;
import com.sd.repay.utils.ThreadFactory;
import com.sd.repay.utils.WebUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;

/**
 * @author sd
 * @Description: 交易成功订单计算平台收益入账
 * @date 2017年10月25日
 */
@Component
public class SuccPayOrderToPlatProfitTask {

    private static Logger log = LoggerFactory.getLogger(SuccPayOrderToPlatProfitTask.class);

    @Autowired
    private AroundPayOrderService aroundPayOrderService;
    @Autowired
    private PayOrderService payOrderService;

    /**
     * 执行平台收益计算及入账
     */
    public void executeSuccPayOrderToPlatProfit() {
        try {
            log.info("成功交易订单计算平台收益入账任务开始");

            List<PayOrder> orderList = payOrderService.getSuccToProfitOrder();
            log.info("需要计算平台收益入账的订单条数：" + orderList.size());
            if (CollectionUtils.isEmpty(orderList)) {
                log.info("没有需要计算平台收益入账的订单");
                return;
            }
            int num = orderList.size();

            if (num >= 10) {
                int threadNum = 1;
                if (num < 50) threadNum = 5;
                if (num >= 1000) threadNum = 10;
                if (num >= 10000) threadNum = 20;

                ExecutorService executor = ThreadFactory.getThread();

                List<Future<List<String>>> results = new ArrayList<>();
                int eachThreadNum = num / threadNum;

                List<PayOrder> subList;

                //拆分集合，由子线程分别执行
                for (int threadIndex = 0; threadIndex < threadNum; threadIndex++) {
                    if (threadIndex == threadNum - 1) {
                        subList = orderList.subList(threadIndex * eachThreadNum, num);
                    } else {
                        subList = orderList.subList(threadIndex * eachThreadNum, threadIndex * eachThreadNum + eachThreadNum);
                    }
                    Future<List<String>> future = executor.submit(new SuccPayOrderToPlatProfitCallable(subList));
                    results.add(future);
                }
                //获得线程处理结果，不对结果进行处理，只是获取，以保证主线程等待子线程执行完
                List<String> totalRes = new ArrayList<>();
                int threadIndex = 0;
                for (Future<List<String>> result : results) {
                    try {
                        if (result.isDone()) {
                            System.out.println("成功交易订单计算平台收益入账任务单线程" + threadIndex + "执行完成了");
                        }
                        totalRes.addAll(result.get());
                        threadIndex++;
                    } catch (Exception e) {
                        e.printStackTrace();
                        log.info(e.toString());
                    }
                }
                executor.shutdown();
                log.info(threadNum + "个线程执行" + totalRes.size() + "个成功交易订单计算平台收益入账任务完成");

            } else {

                for (PayOrder order : orderList) {
                    try {
                        log.info("交易订单[{}]准备计算平台收益入账", order.getOrderNo());
                        aroundPayOrderService.orderSuccToPlatProfit(order.getOrderNo());
                    } catch (Exception e) {
                        log.info("交易订单[{}]计算平台收益入账异常[{}]", new Object[]{order.getOrderNo(), e});
                        e.printStackTrace();
                    }
                }
            }

            WebUtil.removeBlockTaskBySpringId(WebUtil.getClassSimpleName(this.getClass()));

        } catch (Exception e) {
            e.printStackTrace();
            log.error("执行成功交易订单计算平台收益入账任务异常：" + e.getMessage());
        }
    }

    /**
     * 多线程执行成功交易订单计算平台收益入账任务
     */
    private class SuccPayOrderToPlatProfitCallable implements Callable<List<String>> {

        private List<PayOrder> subList = new ArrayList<>();

        public SuccPayOrderToPlatProfitCallable() {
        }

        public SuccPayOrderToPlatProfitCallable(List<PayOrder> subList) {
            this.subList = subList;
        }

        @Override
        public List<String> call() throws Exception {
            List<String> subResList = new ArrayList<>();
            String subOrderNo = "";
            for (PayOrder order : subList) {
                try {
                    subOrderNo = order.getOrderNo();
                    log.info("交易订单[{}]准备计算平台收益入账", subOrderNo);
                    aroundPayOrderService.orderSuccToPlatProfit(subOrderNo);

                } catch (Exception e) {
                    log.info("交易订单[{}]计算平台收益入账异常[{}]", new Object[]{subOrderNo, e});
                    e.printStackTrace();
                } finally {
                    subResList.add("交易订单" + subOrderNo + "计算平台收益入账完成");
                }
            }
            return subResList;
        }
    }
}